<?php

declare (strict_types = 1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://doc.hyperf.io
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
 */
namespace App\Service\Auth;

use App\Constants\ErrorCode;
use App\Dao\AuthAdminLogDao;
use App\Dao\AuthOrganizationDao;
use App\Dao\AuthRoleComponentDao;
use App\Dao\ComponentDao;
use App\Dao\DepartComponentDao;
use App\Dao\MenuComponentDao;
use App\Dao\MenuDao;
use App\Exception\BusinessException;
use App\Utils\ApiUtils;
use App\Utils\FunctionUtil;
use App\Utils\Redis;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use App\Model\Component;

class MenuService
{

    /**
     * @Inject
     * @var Redis
     */
    protected $redis;

    /**
     * @Inject
     * @var MenuDao
     */
    protected $menudao;

    /**
     * @Inject
     * @var MenuComponentDao
     */
    protected $mcdao;

    /**
     * @Inject
     * @var ComponentDao
     */
    protected $cdao;

    /**
     * @Inject
     * @var DepartComponentDao
     */
    protected $ddao;

    public function add($params)
    {
        $map = [];
        $map['menu_name'] = \htmlspecialchars($params['menu_name']);
        $map['pid'] = $params['pid'];
        $map['company_id'] = $params['login_usr']['company_id'];
        $id = $this->menudao->add($map);
        $where = [];
        $where[] = ['id', '=', $id];
        $count = $this->menudao->update($where, ['sort'=>$id]);
        make(AuthAdminLogDao::class)->addLog('添加了栏目' . json_encode($params));
        return ApiUtils::send(ErrorCode::SUCCESS, '添加成功', $id);
    }

    public function edit($params)
    {
        $where = [];
        $where[] = ['id', '=', $params['id']];
        $map['menu_name'] = \htmlspecialchars($params['menu_name']);
        $map['pid'] = $params['pid'];
        $map['update_time'] = \time();
        $count = $this->menudao->update($where, $map);
        make(AuthAdminLogDao::class)->addLog('编辑了栏目' . json_encode($params));
        return ApiUtils::send(ErrorCode::SUCCESS, '编辑成功', $count);

    }

    public function del($params)
    {
        //找出下级
        $is = [];
        $is[] = ['pid', '=', $params['id']];
        $menuIds = $this->getSon([$params['id']]);
        $menuIds[] = intval($params['id']);
        //先查看下有没有部门关联
        $where2 = [];
        //$where2[] = ['menu_id', '=', $params['id']];
        $has = $this->mcdao->searchMoudleId([],$menuIds);
        if (!empty($has)) {
            $res = $this->ddao->searchAll([], $has);
            if (!empty($res)) {
                throw new BusinessException(ErrorCode::ERR_BUESSUS, '该栏目被部门绑定，不能删除');
            }
        }
        $where = [];
        $where[] = ['id', '=', $params['id']];
        $where1 = [];
        $where1[] = ['menu_id', '=', $params['id']];
        Db::beginTransaction();
        try {
            $count = $this->menudao->delete([],$menuIds);
            $count = $this->mcdao->delete([],$menuIds,'menu_id');
            make(AuthAdminLogDao::class)->addLog('删除了栏目' . json_encode($params));
            Db::commit();
            return ApiUtils::send(ErrorCode::SUCCESS, '删除成功', $count);
        } catch (\Throwable $e) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '删除栏目失败' . config('web.err_msg_splite') . $e->getMessage());
        }

    }
    //递归找子类
    public function getSon($pids)
    {
        $menuIds = $this->menudao->searchAllId([], $pids);
        if(!empty($menuIds)){
            $menuIds = array_merge($menuIds,$this->getSon($menuIds));
        }
        return $menuIds;
    }

    public function menuAddComponent($params)
    {   
        $component = \explode(',', $params['component_id']);
        $component = array_unique($component);
        //目录不能添加
        $topIds = [];
        foreach($component as  $v){
            $is = [];
            $is[] = ['pid', '=', $v];
            $info = $this->cdao->searchFirst($is);
            if ($info['is_web'] == Component::IS_DIR) {
                $topIds[] = $v;
            }
        }
        if (!empty($topIds)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, implode(',', $topIds) . '目录功能不能被添加');
        }
        //找出不可以添加的功能
        $unable = [];
        $unable[] = ['menu_id', '!=', $params['menu_id']];
        $unable[] = ['company_id', '=', $params['login_usr']['company_id']];
        $unable = $this->mcdao->searchMoudleId($unable);
        $dupli = array_intersect($component, $unable);
        if (!empty($dupli)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, implode(',', $dupli) . '功能已被其它菜单添加');
        }
        Db::beginTransaction();
        try {
            //找出目录之前的功能
            $where = [];
            $where[] = ['menu_id', '=', $params['menu_id']];
            $component_ids = $this->mcdao->searchMoudleId($where);

            $del = [];
            $del[] = ['menu_id', '=', $params['menu_id']];
            //删除之前
            $this->mcdao->delete($del);
            $map = [];
            $diff = array_diff($component_ids, $component);

            if (!empty($diff)) {
                //删除部门权限缓存
                $where5 = [];
                $where5[] = ['company_id', '=', $params['login_usr']['company_id']];
                //$ori = $this->ddao->searchOriId($where5, $diff);
                $ori = make(AuthOrganizationDao::class)->getByWhereTrait($where5, ['id'])->toArray();
                if (!empty($ori)) {
                    foreach ($ori as $v) {
                        make(ModuleService::class)->clearRedisPermission(0, $v['id']);
                    }
                }
                //删除之前这次没选的模块
                $del1 = [];
                $del1[] = ['company_id', '=', $params['login_usr']['company_id']];
                $this->ddao->delete($del1, $diff);
                //删除权限
                make(AuthRoleComponentDao::class)->deleteByWhereAndInTrait($del1, 'component_id', $diff);
            }

            foreach ($component as $k => $v) {
                if (empty($v)) {
                    continue;
                }
                $tmp = [];
                $tmp['component_id'] = $v;
                $tmp['menu_id'] = $params['menu_id'];
                $tmp['company_id'] = $params['login_usr']['company_id'];
                $map[] = $tmp;
            }
            $count = $this->mcdao->insert($map);
            make(AuthAdminLogDao::class)->addLog('栏目添加了功能' . json_encode($params));
            Db::commit();
            return ApiUtils::send(ErrorCode::SUCCESS, '添加成功', $count);
        } catch (\Throwable $e) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '添加功能失败' . config('web.err_msg_splite') . $e->getMessage());
        }

    }

    public function menuDelComponent($params)
    {

        Db::beginTransaction();
        try {
            //找出自己和下级
            $is = [];
            $is[] = ['pid', '=', $params['component_id']];
            $componentIds = $this->cdao->searchAllId($is);
            $componentIds[] = $params['component_id'];
            $del = [];
            $del[] = ['menu_id', '=', $params['menu_id']];
            //$del[] = ['component_id','=',$params['component_id']];
            $this->mcdao->delete($del, $componentIds);
            //删除部门权限缓存
            $where5 = [];
            $where5[] = ['company_id', '=', $params['login_usr']['company_id']];
            //$ori = $this->ddao->searchOriId($where5, [$params['component_id']]);
            $ori = make(AuthOrganizationDao::class)->getByWhereTrait($where5, ['id'])->toArray();
            if (!empty($ori)) {
                foreach ($ori as $v) {
                    make(ModuleService::class)->clearRedisPermission(0, $v['id']);

                }
            }
            $del1 = [];
            $del1[] = ['company_id', '=', $params['login_usr']['company_id']];
            //$del1[] = ['component_id','=',$params['component_id']];
            $count = $this->ddao->delete($del1, $componentIds);
            //删除角色关联
            make(AuthRoleComponentDao::class)->deleteByWhereAndInTrait($del1, 'component_id', $componentIds);
            make(AuthAdminLogDao::class)->addLog('栏目删除了模块' . json_encode($params));
            Db::commit();
            return ApiUtils::send(ErrorCode::SUCCESS, '删除成功', $count);
        } catch (\Throwable $e) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '删除失败' . config('web.err_msg_splite') . $e->getMessage());
        }

    }

    public function menuMoveComponent($params)
    {
        //$where[] = ['component_id','=',$params['component_id']];
        //找出自己和下级
        $is = [];
        $is[] = ['pid', '=', $params['component_id']];
        $componentIds = $this->cdao->searchAllId($is);
        $componentIds[] = $params['component_id'];
        foreach ($componentIds as $v) {
            $where = [];
            $where[] = ['menu_id', '=', $params['old_menu_id']];
            $where[] = ['component_id', '=', $v];
            $count = $this->mcdao->update($where, ['menu_id' => $params['new_menu_id']]);
        }

        //删除部门权限缓存
        $where5 = [];
        $where5[] = ['company_id', '=', $params['login_usr']['company_id']];
        //$ori = $this->ddao->searchOriId($where5, [$params['component_id']]);
        $ori = make(AuthOrganizationDao::class)->getByWhereTrait($where5, ['id'])->toArray();
        if (!empty($ori)) {
            foreach ($ori as $v) {
                make(ModuleService::class)->clearRedisPermission(0, $v['id']);
            }
        }
        make(AuthAdminLogDao::class)->addLog('移动了栏目模块' . json_encode($params));
        return ApiUtils::send(ErrorCode::SUCCESS, '移动成功', $count);

    }

    public function moveMenuComponent($params)
    {
        if ($params['old_menu_id'] == $params['new_menu_id']) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '自己不能移动至自己');
        }
        $where = [];
        $where[] = ['id', '=', $params['old_menu_id']];
        $has = $this->menudao->searchFirst($where);
        if (empty($has)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '要移动的栏目不存在');
        }
        $where1 = [];
        $where1[] = ['id', '=', $params['new_menu_id']];
        $has = $this->menudao->searchFirst($where1);
        if (empty($has)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '移动至的栏目不存在');
        }
        
        $update['pid'] = $params['new_menu_id'];
        $count = $this->menudao->update($where, $update);
        make(AuthAdminLogDao::class)->addLog('移动栏目功能' . json_encode($params));
        return ApiUtils::send(ErrorCode::SUCCESS, '移动成功', $count);

    }

    //栏目已被分配的功能
    public function menuHasComponent($params)
    {
        $where[] = ['company_id', '=', $params['login_usr']['company_id']];
        $list = $this->mcdao->searchMoudleId($where);
        $list = array_unique($list);
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $list);

    }

    public function move($params)
    {
        $where = [];
        $where[] = ['id', '=', $params['id']];
        $has = $this->menudao->searchFirst($where);
        if (empty($has)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '该栏目不存在');
        }
        if ($params['type'] == 1) { //上移
            $where1 = [];
            $where1[] = ['sort', '>', $has['sort']];
            $where1[] = ['pid', '=', $has['pid']];
            $where1[] = ['company_id', '=', $params['login_usr']['company_id']];
            $next = $this->menudao->MinFirst($where1);
            if(empty($next)){
                throw new BusinessException(ErrorCode::ERR_BUESSUS, '已经是最上层了,无需移动');
            }
        } else {
            $where1 = [];
            $where1[] = ['sort', '<', $has['sort']];
            $where1[] = ['pid', '=', $has['pid']];
            $where1[] = ['company_id', '=', $params['login_usr']['company_id']];
            $next = $this->menudao->MaxFirst($where1);
            if(empty($next)){
                throw new BusinessException(ErrorCode::ERR_BUESSUS, '已经是最下层了,无需移动');
            }
        }
        $count = $this->menudao->update($where, ['sort'=>$next['sort']]);
        $count = $this->menudao->update([['id', '=', $next['id']]], ['sort'=>$has['sort']]);
        make(AuthAdminLogDao::class)->addLog('移动栏目' . json_encode($params));
        return ApiUtils::send(ErrorCode::SUCCESS, '移动成功', $count);

    }

    public function menuList($params)
    {
        $where[] = ['company_id', '=', $params['login_usr']['company_id']];
        $list = $this->menudao->searchAll($where);
        if(empty($list)){
            return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', []);
        }
        foreach($list as $k => $v){
            if (empty($v['components'])) {
                $list[$k]['component'] = [];
            } else{
                $menuIds = array_column($v['components'], 'component_id');
                $list[$k]['component'] = FunctionUtil::webBut($this->cdao->searchAll([], $menuIds, ['id', 'content', 'component_name', 'icon', 'pid', 'url', 'sort', 'identity', 'is_web']));
            }
            unset($list[$k]['components']);
                
            
        }
        $data = FunctionUtil::getTree($list);
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $data);

    }
  

    public function menuAll($params)
    {
        $where[] = ['company_id', '=', $params['login_usr']['company_id']];
        $list = $this->menudao->searchAll($where);
        foreach ($list as $k => $v) {
            unset($list[$k]['components']);
        }
        $list = FunctionUtil::getTree($list);
        
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $list);

    }

}
